Skip to content

Decode CCITT Group 3 and Group 4 fax images - #23

Merged
MPCoreDeveloper merged 1 commit into
mainfrom
feat/ccitt-fax-decoder
Nov 15, 2026
Merged

MPCoreDeveloper merged 1 commit into
mainfrom
feat/ccitt-fax-decoder

Conversation

@MPCoreDeveloper

Copy link
Copy Markdown
Owner

Summary

The second slice of 4a-volledig (ADR-005): CCITTFaxDecode.

  • Pdf/PdfFilters.Ccitt.cs — the T.4 white and black run tables, Group 3 one-dimensional and two-dimensional lines (/K = 0 and /K > 0, with the tag bit after each EOL) and Group 4 (/K < 0, all 2D against the line above). /Columns, /Rows, /BlackIs1, /EncodedByteAlign and /EndOfLine are honoured; a bitmap above the budget is measured and not kept; a stream that stops mid-line is refused.
  • PdfImageFilters dispatches it; a scanned bilevel page now yields Gray8 pixels instead of ImageFilterUnsupported.
  • PdfCcittFilterTests — 8 cases against the committed Pillow/libtiff strips (Assets/ccitt): G4, G3, the BlackIs1 complement, geometry from the image, the budget, no row count, a truncated stream, and a non-CCITT stream.

The 2D fix

b1 is measured from the last changing element (a0) and searched strictly greater than a0, not >= position: after a vertical or horizontal mode the last transition is the new position, so >= position selects the transition just consumed. On the fixture that made line 12's V-3 resolve to 9; with a0 it resolves to 13 and the line completes. ADR-005 records the rule.

Evidence

  • dotnet build -c Release → 0 warnings, 0 errors; dotnet test → 1242 passed, 0 failed on net10.0 and net11.0.
  • Scoped Stryker on PdfFilters.Ccitt.cs → 78.80% (580 mutants: 394 killed, 48 survived, 58 no coverage). docs/mutation-testing.md reads the survivors; three tests were added after the run.
  • The manual is rebuilt (check: ok); ADR-005, parity row 14, chapter 8 and the changelog record the slice.

Next

DCTDecode (JPEG) is the next slice in ADR-005, then JPXDecode and JBIG2Decode.

PdfFilters.Ccitt decodes the T.4 run-length tables, the two-dimensional modes, Group 3 end-of-line and
tag bits, and Group 4 all-2D lines. PdfImageFilters dispatches it and honours /K, /Columns, /Rows,
/BlackIs1, /EncodedByteAlign and /EndOfLine, so a scanned bilevel page yields Gray8 pixels instead of
ImageFilterUnsupported.

The decoder is checked against Group 3 and Group 4 strips Pillow wrote through libtiff (Assets/ccitt),
with the bitmap Pillow decodes as the reference. The two-dimensional b1 is measured from the last
changing element (a0), which is the difference between a line that completes and one whose vertical
mode resolves to the left of the position.

The scoped Stryker run over PdfFilters.Ccitt.cs is 78.80% (580 mutants: 394 killed, 48 survived, 58 no
coverage); the survivors are the parameter defaults, the malformed-stream error branches and a loop
guard, and docs/mutation-testing.md reads them. Three tests were added after the run.

ADR-005, parity row 14, the manual chapter 8 and the changelog record the slice; the manual is rebuilt.
@MPCoreDeveloper
MPCoreDeveloper merged commit cfdace9 into main Nov 15, 2026
8 checks passed
@MPCoreDeveloper
MPCoreDeveloper deleted the feat/ccitt-fax-decoder branch November 15, 2026 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant